import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from nicegui import ui, app
import os
from plotly.subplots import make_subplots
import plotly.io as pio
import hashlib
import json
from pathlib import Path
import numpy as np
from scipy.interpolate import griddata
import plotly.graph_objects as go
import pandas as pd
# 设置全局主题和字体
pio.templates.default = "plotly_white"
pio.templates["plotly_white"].layout.font.update(family="Arial", size=12)

# 用户数据库文件
USER_DB_FILE = 'users.json'


# 初始化用户数据库
def init_user_db():
    if not Path(USER_DB_FILE).exists():
        with open(USER_DB_FILE, 'w') as f:
            json.dump({}, f)


# 密码哈希处理
def hash_password(password):
    return hashlib.sha256(password.encode()).hexdigest()


# 注册新用户
def register_user(username, password):
    with open(USER_DB_FILE, 'r') as f:
        users = json.load(f)

    if username in users:
        return False

    users[username] = {
        'password_hash': hash_password(password),
        'data_access': True
    }

    with open(USER_DB_FILE, 'w') as f:
        json.dump(users, f)

    return True


# 验证用户登录
def verify_user(username, password):
    with open(USER_DB_FILE, 'r') as f:
        users = json.load(f)

    if username not in users:
        return False

    return users[username]['password_hash'] == hash_password(password)


def load_data():
    try:
        df = pd.read_csv('pipe_thickness_loss_dataset.csv')
        ui.notify("数据加载成功！", type='positive')
        return df
    except Exception as e:
        ui.notify(f"数据加载失败: {str(e)}", type='negative')
        return None


def preprocess_data(df):
    if df.isnull().sum().sum() > 0:
        num_cols = df.select_dtypes(include=['float64', 'int64']).columns
        for col in num_cols:
            df[col].fillna(df[col].median(), inplace=True)
        cat_cols = df.select_dtypes(include=['object']).columns
        for col in cat_cols:
            df[col].fillna(df[col].mode()[0], inplace=True)

    num_cols = df.select_dtypes(include=['float64', 'int64']).columns
    for col in num_cols:
        Q1 = df[col].quantile(0.25)
        Q3 = df[col].quantile(0.75)
        IQR = Q3 - Q1
        lower_bound = Q1 - 1.5 * IQR
        upper_bound = Q3 + 1.5 * IQR
        df[col] = df[col].apply(lambda x: lower_bound if x < lower_bound else (upper_bound if x > upper_bound else x))

    return df


def create_3d_scatter(df, x_col, y_col, z_col, color_col):
    if not pd.api.types.is_numeric_dtype(df[color_col]):
        df[color_col + '_code'] = pd.factorize(df[color_col])[0]
        color_col = color_col + '_code'

    fig = px.scatter_3d(
        df,
        x=x_col,
        y=y_col,
        z=z_col,
        color=color_col,
        title=f'3D散点图: {x_col} vs {y_col} vs {z_col}',
        hover_data=['Pipe_ID', 'Material', 'Condition'],
        height=700,
        color_continuous_scale='Rainbow',
        range_color=[df[color_col].min(), df[color_col].max()]
    )

    fig.update_traces(
        marker=dict(
            size=8,
            opacity=0.9,
            line=dict(width=0),
            symbol='circle',
            sizemode='diameter'
        ),
        selector=dict(mode='markers')
    )

    fig.update_layout(
        scene=dict(
            xaxis=dict(title=x_col, range=[df[x_col].min() - 5, df[x_col].max() + 5]),
            yaxis=dict(title=y_col, range=[df[y_col].min() - 1, df[y_col].max() + 1]),
            zaxis=dict(title=z_col, range=[df[z_col].min() - 1, df[z_col].max() + 1]),
            camera=dict(
                eye=dict(x=1.2, y=1.2, z=0.6),
                up=dict(x=0, y=0, z=1)
            ),
            aspectmode='cube'
        ),
        coloraxis_colorbar=dict(
            title=color_col.replace('_code', '') if '_code' in color_col else color_col
        ),
        plot_bgcolor='white',
        paper_bgcolor='white'
    )

    return fig


def create_boxplot(df, x_col, y_col):
    fig = px.box(
        df,
        x=x_col,
        y=y_col,
        title=f'箱线图: {x_col} vs {y_col}',
        color=x_col,
        height=600,
        color_discrete_sequence=px.colors.qualitative.Pastel
    )

    fig.update_layout(
        xaxis_title=x_col,
        yaxis_title=y_col,
        boxmode='group',
        showlegend=True,
        plot_bgcolor='white',
        paper_bgcolor='white'
    )

    return fig


def create_heatmap(df, columns):
    corr = df[columns].corr()
    fig = px.imshow(
        corr,
        text_auto=True,
        aspect="auto",
        title='相关性热力图',
        height=600,
        color_continuous_scale='Blues'
    )

    fig.update_layout(
        xaxis_title="特征",
        yaxis_title="特征",
        coloraxis_colorbar=dict(title="相关系数"),
        plot_bgcolor='white',
        paper_bgcolor='white'
    )

    return fig


def create_histogram(df, col, color_col=None):
    fig = px.histogram(
        df,
        x=col,
        color=color_col,
        title=f'{col}分布直方图',
        marginal="box",
        height=600,
        nbins=30,
        color_discrete_sequence=px.colors.qualitative.Pastel
    )

    fig.update_layout(
        xaxis_title=col,
        yaxis_title="计数",
        bargap=0.1,
        plot_bgcolor='white',
        paper_bgcolor='white'
    )

    return fig


def create_scatter_matrix(df, dimensions, color_col):
    fig = px.scatter_matrix(
        df,
        dimensions=dimensions,
        color=color_col,
        title='散点矩阵图',
        height=800,
        color_discrete_sequence=px.colors.qualitative.Pastel
    )

    fig.update_traces(
        diagonal_visible=False,
        showupperhalf=False,
        marker=dict(size=3, opacity=0.6)
    )

    fig.update_layout(
        plot_bgcolor='white',
        paper_bgcolor='white'
    )

    return fig






def create_line_chart(df, x_col, y_col, color_col):
    # 数据预处理：按分组计算均值
    df_agg = df.groupby([x_col, color_col], as_index=False)[y_col].mean()

    # 高对比度色板
    material_colors = {
        'Copper': '#1f77b4',
        'Cast Iron': '#ff7f0e',
        'Aluminum': '#2ca02c',
        'Steel': '#d62728',
        'PVC': '#9467bd'
    }

    fig = px.line(
        df_agg,
        x=x_col,
        y=y_col,
        color=color_col,
        color_discrete_map=material_colors,
        title=f' 折线图{x_col} vs {y_col}',  # 通用化标题
        height=600
    )

    # 动态布局优化
    fig.update_layout(
        plot_bgcolor='white',
        paper_bgcolor='white',
        xaxis=dict(
            title=x_col,  # 动态显示X轴名称
            gridcolor='lightgray',
            showspikes=True,  # 显示悬停时的辅助线
            spikethickness=1
        ),
        yaxis=dict(
            title=y_col,  # 动态显示Y轴名称
            gridcolor='lightgray',
            showspikes=True
        ),
        hovermode="x unified",
        hoverlabel=dict(
            bgcolor="white",
            font_size=12
        )
    )

    # 为每条线添加独特样式
    for i, trace in enumerate(fig.data):
        trace.update(
            line=dict(width=2.5),
            opacity=0.9,
            mode="lines+markers",
            marker=dict(
                size=6,
                symbol=i + 1,  # 不同形状标记
                line=dict(width=1, color='DarkSlateGrey')
            ),
            hovertemplate=f"""
                {color_col}: {trace.name}<br>
                {x_col}: %{{x}}<br>
                {y_col}: %{{y}}<extra></extra>
            """  # 动态显示列名
        )

    return fig

def create_bar_chart(df, x_col, y_col, color_col):
    fig = px.bar(
        df,
        x=x_col,
        y=y_col,
        color=color_col,
        title=f'柱状图: {x_col} vs {y_col}',
        height=600
    )
    fig.update_layout(
        plot_bgcolor='white',
        paper_bgcolor='white'
    )
    return fig


def create_density_chart(df, col, color_col):
    fig = px.density_contour(
        df,
        x=col,
        color=color_col,
        title=f'{col}密度分布图',
        height=600
    )
    fig.update_layout(
        plot_bgcolor='white',
        paper_bgcolor='white'
    )
    return fig




def create_surface_chart(df, x_col, y_col, z_col, color_col=None):
    """创建高鲜艳度的3D曲面图，移除底部等高线"""
    try:
        # 数据预处理
        df = df.copy()
        for col in [x_col, y_col, z_col]:
            if not pd.api.types.is_numeric_dtype(df[col]):
                df[col] = pd.to_numeric(df[col], errors='coerce')

        # 移除无效数据
        df = df.dropna(subset=[x_col, y_col, z_col])

        # 创建更密集的网格数据（使曲面更平滑）
        x_unique = np.linspace(df[x_col].min(), df[x_col].max(), 80)
        y_unique = np.linspace(df[y_col].min(), df[y_col].max(), 80)
        xx, yy = np.meshgrid(x_unique, y_unique)

        # 使用griddata插值创建z值矩阵
        zz = griddata(
            (df[x_col], df[y_col]),
            df[z_col],
            (xx, yy),
            method='cubic'
        )

        # 自定义鲜艳的色彩方案（红黄紫粉蓝渐变）
        custom_colorscale = [
            [0.0, 'rgb(255,0,255)'], # 紫色
            [0.3, 'rgb(255,0,0)'],  # 红色
            [0.5, 'rgb(255,255,0)'],  # 黄色
            [0.75, 'rgb(255,192,203)'], # 粉色
            [1.0, 'rgb(0,0,255)']     # 蓝色
        ]

        # 创建高鲜艳度的曲面图 - 移除contours_z参数
        fig = go.Figure(data=[
            go.Surface(
                x=xx,
                y=yy,
                z=zz,
                colorscale=custom_colorscale,
                showscale=True,
                opacity=1.0,
                surfacecolor=zz,
                lighting=dict(
                    ambient=0.25,
                    diffuse=0.95,
                    specular=0.05,
                    roughness=0.25
                ),
                lightposition=dict(x=200, y=200, z=1500),
                colorbar=dict(
                    thickness=25,
                    len=0.8,
                    title=dict(
                        text=z_col,
                        font=dict(size=14, color='black')
                    ),
                    tickfont=dict(size=12, color='black')
                )
                # 已移除contours_z参数
            )
        ])

        # 设置高对比度的布局
        fig.update_layout(
            title=dict(
                text=f'<b>3D曲面图: {x_col} vs {y_col} vs {z_col}</b>',
                font=dict(size=18, color='darkblue'),
                x=0.5,
                xanchor='center'
            ),
            scene=dict(
                xaxis_title=f'<b>{x_col}</b>',
                yaxis_title=f'<b>{y_col}</b>',
                zaxis_title=f'<b>{z_col}</b>',
                camera=dict(
                    eye=dict(x=1.6, y=1.6, z=0.8),
                    up=dict(x=0, y=0, z=1),
                    center=dict(x=0, y=0, z=0)
                ),
                xaxis=dict(
                    backgroundcolor='rgba(255,255,255,0.1)',
                    gridcolor='rgba(100,100,100,0.5)',
                    showbackground=True,
                    title_font=dict(size=14, color='darkred')
                ),
                yaxis=dict(
                    backgroundcolor='rgba(255,255,255,0.1)',
                    gridcolor='rgba(100,100,100,0.5)',
                    showbackground=True,
                    title_font=dict(size=14, color='darkgreen')
                ),
                zaxis=dict(
                    backgroundcolor='rgba(255,255,255,0.1)',
                    gridcolor='rgba(100,100,100,0.5)',
                    showbackground=True,
                    title_font=dict(size=14, color='darkblue')
                ),
                aspectratio=dict(x=1, y=1, z=0.7),
                bgcolor='rgba(245,245,245,0.9)'
            ),
            height=850,
            margin=dict(l=60, r=60, b=60, t=90),
            plot_bgcolor='white',
            paper_bgcolor='white',
            font=dict(family="Arial", size=12, color="black")
        )

        return fig

    except Exception as e:
        print(f"创建曲面图时出错: {str(e)}")
        # 创建错误提示图
        fig = go.Figure()
        fig.update_layout(
            title="无法生成曲面图: 数据不符合要求",
            annotations=[
                dict(
                    text=f"错误: {str(e)}",
                    x=0.5,
                    y=0.5,
                    showarrow=False,
                    font=dict(size=16, color='red')
                )
            ],
            plot_bgcolor='white',
            paper_bgcolor='white'
        )
        return fig

def create_default_chart(df):
    fig = make_subplots(
        rows=1, cols=2,
        specs=[[{'type': 'scatter3d'}, {'type': 'xy'}]],
        subplot_titles=('3D散点图: 管道尺寸与厚度损失', '厚度损失分布直方图')
    )

    scatter = px.scatter_3d(
        df,
        x='Diameter_mm',
        y='Strength_MPa',
        z='Thickness_mm',
        color='Material'
    )

    for trace in scatter.data:
        fig.add_trace(trace, row=1, col=1)

    hist = px.histogram(
        df,
        x='Thickness_Loss_mm',
        color='Material',
        nbins=30
    )

    for trace in hist.data:
        fig.add_trace(trace, row=1, col=2)

    fig.update_layout(
        height=600,
        showlegend=True,
        margin=dict(l=50, r=50, b=50, t=50),
        plot_bgcolor='white',
        paper_bgcolor='white'
    )

    fig.update_scenes(
        row=1, col=1,
        xaxis_title='直径(mm)',
        yaxis_title='厚度(mm)',
        zaxis_title='厚度损失(mm)'
    )

    fig.update_xaxes(title_text='厚度损失(mm)', row=1, col=2)
    fig.update_yaxes(title_text='计数', row=1, col=2)

    return fig


# 定义所有页面路由
def init_pages():
    @ui.page('/')
    def home():
        ui.navigate.to('/login')

    @ui.page('/login')
    def login():
        with ui.column().classes('absolute-center items-center'):
            ui.label('登录').classes('text-2xl font-bold mb-4 text-blue-700')

            username = ui.input('用户名').props('outlined').classes('w-64 mb-2')
            password = ui.input('密码', password=True, password_toggle_button=True).props('outlined').classes(
                'w-64 mb-4')

            with ui.row():
                ui.button('登录', on_click=lambda: handle_login(username.value, password.value)).classes(
                    'bg-blue-500 text-white hover:bg-blue-600')
                ui.button('注册', on_click=lambda: ui.navigate.to('/register')).classes(
                    'bg-green-500 text-white hover:bg-green-600')

    @ui.page('/register')
    def register():
        with ui.column().classes('absolute-center items-center'):
            ui.label('注册新账户').classes('text-2xl font-bold mb-4 text-blue-700')

            username = ui.input('用户名').props('outlined').classes('w-64 mb-2')
            password = ui.input('密码', password=True, password_toggle_button=True).props('outlined').classes(
                'w-64 mb-2')
            confirm_password = ui.input('确认密码', password=True, password_toggle_button=True).props(
                'outlined').classes('w-64 mb-4')

            with ui.row():
                ui.button('注册', on_click=lambda: handle_register(
                    username.value,
                    password.value,
                    confirm_password.value
                )).classes('bg-green-500 text-white hover:bg-green-600')
                ui.button('返回登录', on_click=lambda: ui.navigate.to('/login')).classes(
                    'bg-blue-500 text-white hover:bg-blue-600')

    @ui.page('/analysis')
    def analysis():
        raw_df = load_data()
        if raw_df is None:
            ui.notify("无法加载数据，请检查数据文件", type='negative')
            ui.navigate.to('/login')
            return

        df = preprocess_data(raw_df.copy())
        numeric_cols = df.select_dtypes(include=['float64', 'int64']).columns.tolist()
        categorical_cols = df.select_dtypes(include=['object']).columns.tolist()

        with ui.header().classes('bg-blue-500 text-white p-4 shadow-md'):
            with ui.row().classes('w-full max-w-7xl mx-auto items-center'):
                ui.label('管道厚度损失分析系统').classes('text-2xl font-bold')
                ui.space()
                ui.button('退出', on_click=lambda: ui.navigate.to('/login')).classes(
                    'bg-red-500 text-white hover:bg-red-600')

        # 主容器 - 使用flex布局实现左右分栏
        with ui.row().classes('w-full max-w-7xl mx-auto p-4 gap-4 h-[calc(100vh-80px)]'):
            # 控制面板 - 左侧，宽度30%，添加滚动条
            with ui.column().classes(
                    'w-[30%] bg-gray-50 p-4 rounded-lg shadow-md overflow-y-auto border border-gray-200'):
                ui.label('控制面板').classes('text-xl font-bold mb-4 text-blue-700 border-b pb-2')

                # 添加数据集预览按钮
                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200'):
                    ui.button('预览数据集', on_click=lambda: show_data_preview()).classes(
                        'w-full bg-blue-500 text-white hover:bg-blue-600')

                # 图表类型选择 - 改为按钮组形式
                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200'):
                    ui.label('选择图表类型').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    with ui.button_group().classes('w-full'):
                        with ui.row().classes('w-full flex-wrap gap-1'):
                            ui.button('3D散点图', on_click=lambda: set_chart_type('3D散点图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('箱线图', on_click=lambda: set_chart_type('箱线图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('热力图', on_click=lambda: set_chart_type('热力图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('直方图', on_click=lambda: set_chart_type('直方图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                        with ui.row().classes('w-full flex-wrap gap-1'):
                            ui.button('散点矩阵图', on_click=lambda: set_chart_type('散点矩阵图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('组合视图', on_click=lambda: set_chart_type('组合视图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('折线图', on_click=lambda: set_chart_type('折线图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('柱状图', on_click=lambda: set_chart_type('柱状图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                        with ui.row().classes('w-full flex-wrap gap-1'):
                            ui.button('密度图', on_click=lambda: set_chart_type('密度图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                            ui.button('曲面图', on_click=lambda: set_chart_type('曲面图')) \
                                .classes('flex-grow bg-blue-700 text-white hover:bg-blue-800')
                    # 当前选择的图表类型状态
                    chart_type = ui.label('当前选择: 组合视图').classes('text-sm mt-2 text-gray-600')

                # 图表参数配置 - 使用卡片分组
                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '3D散点图' in val):
                    ui.label('3D散点图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    x_axis = ui.select(options=numeric_cols, label='X轴', value='Diameter_mm').props(
                        'outlined').classes('w-full mb-2')
                    y_axis = ui.select(options=numeric_cols, label='Y轴', value='Thickness_mm').props(
                        'outlined').classes('w-full mb-2')
                    z_axis = ui.select(options=numeric_cols, label='Z轴', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full mb-2')
                    color_by = ui.select(options=categorical_cols, label='颜色分类', value='Material').props(
                        'outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '箱线图' in val):
                    ui.label('箱线图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    box_x = ui.select(options=categorical_cols, label='分类列', value='Material').props(
                        'outlined').classes('w-full mb-2')
                    box_y = ui.select(options=numeric_cols, label='数值列', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '热力图' in val):
                    ui.label('热力图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    heatmap_cols = ui.select(
                        options=numeric_cols,
                        label='选择列',
                        value=numeric_cols[:5],
                        multiple=True
                    ).props('outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '直方图' in val):
                    ui.label('直方图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    hist_col = ui.select(options=numeric_cols, label='选择列', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full mb-2')
                    hist_color = ui.select(options=categorical_cols + [None], label='颜色分类(可选)',
                                           value='Material').props('outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '散点矩阵图' in val):
                    ui.label('散点矩阵图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    scatter_matrix_cols = ui.select(
                        options=numeric_cols,
                        label='选择列',
                        value=numeric_cols[:4],
                        multiple=True
                    ).props('outlined').classes('w-full mb-2')
                    scatter_matrix_color = ui.select(options=categorical_cols, label='颜色分类',
                                                     value='Material').props('outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '折线图' in val):
                    ui.label('折线图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    line_x = ui.select(options=numeric_cols, label='X轴', value='Diameter_mm').props(
                        'outlined').classes('w-full mb-2')
                    line_y = ui.select(options=numeric_cols, label='Y轴', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full mb-2')
                    line_color = ui.select(options=categorical_cols, label='颜色分类', value='Material').props(
                        'outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '柱状图' in val):
                    ui.label('柱状图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    bar_x = ui.select(options=categorical_cols, label='X轴', value='Material').props(
                        'outlined').classes('w-full mb-2')
                    bar_y = ui.select(options=numeric_cols, label='Y轴', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full mb-2')
                    bar_color = ui.select(options=categorical_cols, label='颜色分类', value='Condition').props(
                        'outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '密度图' in val):
                    ui.label('密度图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    density_col = ui.select(options=numeric_cols, label='选择列', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full mb-2')
                    density_color = ui.select(options=categorical_cols, label='颜色分类', value='Material').props(
                        'outlined').classes('w-full')

                with ui.card().classes('w-full mb-4 p-4 bg-white border border-gray-200').bind_visibility_from(
                        chart_type, 'text', lambda val: '曲面图' in val):
                    ui.label('曲面图参数').classes('text-lg font-semibold mb-2 text-gray-700 border-b pb-2')
                    surface_x = ui.select(options=numeric_cols, label='X轴', value='Diameter_mm').props(
                        'outlined').classes('w-full mb-2')
                    surface_y = ui.select(options=numeric_cols, label='Y轴', value='Thickness_mm').props(
                        'outlined').classes('w-full mb-2')
                    surface_z = ui.select(options=numeric_cols, label='Z轴', value='Thickness_Loss_mm').props(
                        'outlined').classes('w-full mb-2')
                    surface_color = ui.select(options=categorical_cols, label='颜色分类', value='Material').props(
                        'outlined').classes('w-full')

                # 操作按钮
                with ui.row().classes('w-full justify-between mt-4'):
                    ui.button('更新图表', on_click=lambda: update_chart()).classes(
                        'bg-blue-500 text-white hover:bg-blue-600 flex-grow')

                # 数据统计信息
                with ui.expansion('数据统计信息', icon='info').classes('w-full mt-4 bg-white border border-gray-200'):
                    with ui.card().classes('w-full p-4'):
                        ui.label(f"总记录数: {len(df)}").classes('text-sm')
                        ui.label(f"数值列: {', '.join(numeric_cols)}").classes('text-sm')
                        ui.label(f"分类列: {', '.join(categorical_cols)}").classes('text-sm')

                # 数据筛选
                with ui.expansion('数据筛选', icon='filter_alt').classes('w-full mt-4 bg-white border border-gray-200'):
                    with ui.card().classes('w-full p-4'):
                        condition_select = ui.select(
                            options=['全部'] + df['Condition'].unique().tolist(),
                            label='管道状态',
                            value='全部'
                        ).props('outlined').classes('w-full mb-2')
                        material_select = ui.select(
                            options=['全部'] + df['Material'].unique().tolist(),
                            label='材料类型',
                            value='全部'
                        ).props('outlined').classes('w-full mb-2')
                        ui.button('应用筛选', on_click=lambda: apply_filters()).classes(
                            'w-full bg-green-500 text-white hover:bg-green-600')

            # 可视化结果 - 右侧，宽度70%，背景改为白色
            with ui.column().classes('flex-1 bg-white p-4 rounded-lg shadow-md border border-gray-200 min-h-[600px]'):
                ui.label('可视化结果').classes('text-xl font-bold mb-4 text-blue-700 border-b pb-2')
                # 创建默认图表容器
                plot_container = ui.column().classes('w-full h-full')
                # 创建数据预览容器，初始隐藏
                data_preview_container = ui.column().classes('w-full h-full').style('display: none')

                # 初始化默认图表
                default_fig = create_default_chart(df)
                plot_container.clear()
                with plot_container:
                    ui.plotly(default_fig).classes('w-full h-full')

        def set_chart_type(type_name):
            chart_type.text = f'当前选择: {type_name}'
            update_chart()

        def show_data_preview():
            # 显示数据预览，隐藏图表
            plot_container.style('display: none')
            data_preview_container.style('display: block')

            # 清空并重新填充数据预览容器
            data_preview_container.clear()
            with data_preview_container:
                ui.label('数据集预览').classes('text-lg font-bold mb-2')
                # 创建表格并设置样式
                table = ui.table.from_pandas(df.head(1000)).classes('w-full max-h-[600px]')
                table.add_slot('body-cell', '''
                    <q-td :props="props" style="padding: 4px 8px;">
                        {{ props.value }}
                    </q-td>
                ''')
                # 添加返回按钮
                ui.button('返回图表视图', on_click=lambda: show_chart_view()).classes(
                    'mt-4 bg-blue-500 text-white hover:bg-blue-600')

        def show_chart_view():
            # 显示图表，隐藏数据预览
            data_preview_container.style('display: none')
            plot_container.style('display: block')

        def update_chart():
            nonlocal df
            current_chart = chart_type.text.replace('当前选择: ', '')

            if current_chart == '3D散点图':
                fig = create_3d_scatter(
                    df,
                    x_axis.value,
                    y_axis.value,
                    z_axis.value,
                    color_by.value
                )
            elif current_chart == '箱线图':
                fig = create_boxplot(
                    df,
                    box_x.value,
                    box_y.value
                )
            elif current_chart == '热力图':
                fig = create_heatmap(
                    df,
                    heatmap_cols.value
                )
            elif current_chart == '直方图':
                fig = create_histogram(
                    df,
                    hist_col.value,
                    hist_color.value if hist_color.value != 'None' else None
                )
            elif current_chart == '散点矩阵图':
                fig = create_scatter_matrix(
                    df,
                    scatter_matrix_cols.value,
                    scatter_matrix_color.value
                )
            elif current_chart == '组合视图':
                fig = create_default_chart(df)
            elif current_chart == '折线图':
                fig = create_line_chart(
                    df,
                    line_x.value,
                    line_y.value,
                    line_color.value
                )
            elif current_chart == '柱状图':
                fig = create_bar_chart(
                    df,
                    bar_x.value,
                    bar_y.value,
                    bar_color.value
                )
            elif current_chart == '密度图':
                fig = create_density_chart(
                    df,
                    density_col.value,
                    density_color.value
                )
            elif current_chart == '曲面图':
                fig = create_surface_chart(
                    df,
                    surface_x.value,
                    surface_y.value,
                    surface_z.value,
                    surface_color.value
                )

            # 更新图表视图
            plot_container.clear()
            with plot_container:
                ui.plotly(fig).classes('w-full h-full')

            # 确保显示的是图表视图
            show_chart_view()

        def apply_filters():
            nonlocal df
            filtered_df = raw_df.copy()
            if condition_select.value != '全部':
                filtered_df = filtered_df[filtered_df['Condition'] == condition_select.value]
            if material_select.value != '全部':
                filtered_df = filtered_df[filtered_df['Material'] == material_select.value]
            df = preprocess_data(filtered_df)
            ui.notify(f"筛选后数据: {len(df)}条记录", type='positive')
            update_chart()

        # 初始化视图
        update_chart()


def handle_login(username, password):
    if not username or not password:
        ui.notify('请输入用户名和密码', type='negative')
        return

    if verify_user(username, password):
        ui.notify('登录成功!', type='positive')
        ui.navigate.to('/analysis')
    else:
        ui.notify('用户名或密码错误', type='negative')


def handle_register(username, password, confirm_password):
    if not username or not password:
        ui.notify('请输入用户名和密码', type='negative')
        return

    if password != confirm_password:
        ui.notify('两次输入的密码不一致', type='negative')
        return

    if register_user(username, password):
        ui.notify('注册成功! 请登录', type='positive')
        ui.navigate.to('/login')
    else:
        ui.notify('用户名已存在', type='negative')


if __name__ in ["__main__", "__mp_main__"]:
    init_user_db()

    if not os.path.exists('pipe_thickness_loss_dataset.csv'):
        ui.notify("错误: 数据集文件 'pipe_thickness_loss_dataset.csv' 不存在!", type='negative')

    # 初始化所有页面
    init_pages()

    # 默认跳转到登录页面
    ui.navigate.to('/login')

    ui.run(title='管道厚度损失分析系统', port=8080, reload=False)